package com.qys.wallet.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qys.livesMall.cache.utils.CacheUtils;
import com.qys.wallet.model.dto.WalletCoinAddrQueryDTO;
import com.qys.wallet.model.entity.WalletCoinAddr;
import com.qys.wallet.mapper.WalletCoinAddrMapper;
import com.qys.wallet.model.entity.WalletCoinRecord;
import com.qys.wallet.model.vo.WalletCoinAddrPageVO;
import com.qys.wallet.pay.hyperbc.HyperbcService;
import com.qys.wallet.pay.hyperbc.dto.resp.AddressChildDTO;
import com.qys.wallet.pay.hyperbc.dto.resp.AddressDTO;
import com.qys.wallet.pay.hyperbc.dto.resp.HyWlCollBackDTO;
import com.qys.wallet.service.WalletCoinAddrService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qys.wallet.service.WalletCoinRecordService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;

/**
 * <p>
 * 用户充值地址表 服务实现类
 * </p>
 *
 * @author
 * @since 2023-09-25
 */
@Service
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class WalletCoinAddrServiceImpl extends ServiceImpl<WalletCoinAddrMapper, WalletCoinAddr> implements WalletCoinAddrService {

    private final CacheUtils cacheUtils;
    private final HyperbcService hyperbcService;
    private final WalletCoinRecordService coinRecordService;


    @Override
    public Page<WalletCoinAddrPageVO> pageBySys(WalletCoinAddrQueryDTO query) {
        Page<WalletCoinAddr> page = new Page<>(query.getPageNum(), query.getPageSize());
        return baseMapper.pageBySys(page, query);
    }


    /**
     * 获取充值地址
     *
     * @param chainName 主链类型
     * @param userId    绑定用户
     * @param type      类型
     * @return 充值地址
     */
    @Override
    public String createAddress(String chainName, String userId, Byte type) {
        String address = null;
        //设置锁名
        String lockName = "userAddr:" + userId + "-" + type;
        //获得锁
        boolean isLock = cacheUtils.getLock(lockName, CacheUtils.LOCK_WAITTIME_SECONDS);
        try {
            if (isLock) {
                WalletCoinAddr coinAddr = baseMapper.selectOne(Wrappers.<WalletCoinAddr>lambdaQuery()
                        .eq(WalletCoinAddr::getUserId, userId)
                        .eq(WalletCoinAddr::getType, type)
                        .eq(WalletCoinAddr::getChainName, chainName)
                );
                if (coinAddr == null) {
                    boolean flag = false;
                    //获取还未绑定的地址
                    String noBindAddress = syncAddressStatus(chainName);
                    if (null != noBindAddress) {
                        address = noBindAddress;
                    } else {
                        //没有绑定地址,直接获取地址
                        address = hyperbcService.getAddress(chainName);
                        flag = true;
                    }
                    coinAddr = new WalletCoinAddr();
                    coinAddr.setAddress(address);
                    coinAddr.setType(type);
                    coinAddr.setChainName(chainName);
                    coinAddr.setCreateTime(System.currentTimeMillis());
                    coinAddr.setUserId(userId);
                    int insert = baseMapper.insert(coinAddr);
                    log.info("用户:" + userId + "用户类型" + type + ",生成地址:" + address + ",地址主链：" + chainName);
                    if (flag && insert == 1) {
                        //同步地址状态
                        hyperbcService.syncAddressStatus(address, type + "_" + userId);
                    }
                } else {
                    address = coinAddr.getAddress();
                }
                return address;
            }
        } finally {
            if (isLock) {
                //释放锁
                cacheUtils.releaseLock(lockName);
            }
        }
        return address;
    }

    /**
     * 获取充值地址并绑定指定用户
     *
     * @param chainName 主链类型
     * @param userId    绑定用户
     * @param type      类型
     * @return 充值地址
     */
    @Override
    public String getAddress(String chainName, String userId, Byte type) {
        WalletCoinAddr coinAddr = baseMapper.selectOne(Wrappers.<WalletCoinAddr>lambdaQuery()
                .eq(WalletCoinAddr::getUserId, userId)
                .eq(WalletCoinAddr::getType, type)
                .eq(WalletCoinAddr::getChainName, chainName)
        );
        return coinAddr == null ? createAddress(chainName, userId, type) : coinAddr.getAddress();
    }

    /**
     * 提现
     *
     * @param amount   提现数量
     * @param orderNo  提现单号
     * @param address  提现地址
     * @param userId   用户信息
     * @param coinName 提现币种
     * @return
     */
    @Override
    public boolean transfer(BigDecimal amount, String orderNo, String address, String userId, String coinName) {
        //判断地址有效性
        hyperbcService.checkAddress(coinName,address);

//        hyperbcService.transfer()
        return false;
    }

    @Override
    public boolean rechargeCallBack(HyWlCollBackDTO data) {
        long count = coinRecordService.count(Wrappers.<WalletCoinRecord>lambdaQuery().eq(WalletCoinRecord::getTxid, data.getTxid()));
        if (count > 0) {
            log.error("重复充值Txid[{}]！！！", data.getTxid());
            return false;
        }
        //通过地址查询到绑定信息
        WalletCoinAddr mallCoinAddr = baseMapper.selectById(data.getAddress());
        if (mallCoinAddr == null) {
            log.error("未查询到绑定地址信息[{}]！！！", data.getAddress());
            return false;
        }
        //TODO 编写充值业务

        //创建地址出入账记录
        coinRecordService.createRecord(data, (byte) 1);
        return false;
    }

    /**
     * 提现回调
     *
     * @param data 回调data参数
     * @return
     */
    @Override
    public boolean withdrawalCallBack(HyWlCollBackDTO data) {
        long count = coinRecordService.count(Wrappers.<WalletCoinRecord>lambdaQuery().eq(WalletCoinRecord::getTxid, data.getTxid()));
        if (count > 0) {
            log.error("重复充值Txid[{}]！！！", data.getTxid());
            return false;
        }
        //TODO 编写提现业务
        //创建地址出入账记录
        coinRecordService.createRecord(data, (byte) 1);
        return false;
    }
    /**
     * 同步地址
     *
     * @param chainName 主链类型
     * @return
     */
    private String syncAddressStatus(String chainName) {
        //获取还未绑定的地址
        AddressDTO addressList = hyperbcService.getAddressList(chainName, 2);
        log.info("查询到未绑定地址数量->{},地址为：{}", addressList.getList().size(), addressList.getList());
        if (addressList.getList().size() > 0) {
            AddressChildDTO addressChildDTO = addressList.getList().get(0);
            //判断地址是否被绑定
            WalletCoinAddr addr = baseMapper.selectById(addressChildDTO.getAddress());
            if (addr != null) {
                log.info("未提交绑定状态,重新提交绑定！！！");
                hyperbcService.syncAddressStatus(addr.getAddress(), addr.getType() + "_" + addr.getUserId());
                syncAddressStatus(chainName);
            }
            return addressChildDTO.getAddress();
        }
        return null;
    }


}
